package com.link.base.base.user.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.link.base.base.appinfo.model.AppMobileInfo;
import com.link.base.base.appinfo.service.AppMobileInfoService;
import com.link.base.base.orgnization.model.Orgnization;
import com.link.base.base.orgnization.service.OrgnizationService;
import com.link.base.base.user.model.*;
import com.link.base.base.user.service.*;
import com.link.base.enterprise.model.CoreEnterprise;
import com.link.base.user.model.CoreUser;
import com.link.core.basic.annotations.JsonParam;
import com.link.core.basic.interceptor.SecurityInterceptor;
import com.link.core.basic.service.BasicServiceException;
import com.link.core.cllog.LCLogger;
import com.link.core.util.*;
import com.link.core.util.redisclient.LinkRedisClient;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.link.core.basic.service.BasicService.*;

/**
 * @author unknown
 * @date unknown
 * @comments 登录
 */
@Controller
@RequestMapping("/base/user")
public class LoginController {

    private static final Logger logger = LogManager.getLogger(LoginController.class);

    private static final String APP_ENTRANCE = "app";

    @Resource
    private UserService userService;

    @Resource
    private LoginLogService loginLogService;

    @Resource
    private LoginService loginService;

    @Resource
    private AppMobileInfoService appMobileInfoService;

    @Resource
    private OrgnizationService orgnizationService;

    @Resource
    private ThirdLoginService thirdLoginService;

    @Resource
    private OauthTokenService oauthTokenService;


    /**
     * 后台查询当前登录用户信息
     *
     * @param session
     * @param request
     * @param response
     * @return map
     * @throws Exception
     */
    @RequestMapping(value = "/getUserCtx", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> getUserCtx(HttpSession session, HttpServletRequest request, HttpServletResponse response) throws Exception {
        Map<String, Object> result = new HashMap<String, Object>();
        try {
            Map<String, Object> ctx = new HashMap<String, Object>();
            CoreUser userCache = UserUtil.getUser();
            User user = loginService.getUser(userCache.getUsername(), null);
            Long userId = null;
            String username = "";
            String firstName = "";
            String role = "";
            Long orgId = null;
            String orgName = null;
            Long postnId = null;
            String postnName = "";
            Long corpId = null;
            String corpName = "";
            String userIcon = "";
            //经销商Id
            Long acctId = null;
            //经销商姓名
            String acctName = "";
            //用户类型
            String userType = "";
            //上次登录时间
            String lastLoginDate = "";
            //客户状态
            String acctStatus = "";
            //性别
            String gender = "";
            // 使用语言
            String loginLanguage = "";
            if (user != null) {
                userId = user.getId();
                username = user.getUsername();
                role = user.getRole();
                orgId = user.getOrgId();
                orgName = user.getOrgName();
                postnId = userCache.getPostnId();
                postnName = userCache.getPostnName();
                firstName = user.getFirstName();
                corpId = user.getCorpid();
                corpName = user.getCorpName();
                userIcon = user.getUserIcon();
                //经销商Id
                acctId = user.getAcctId();
                //经销商姓名
                acctName = user.getAcctName();
                userType = user.getEmpType();
                lastLoginDate = user.getLastLoginDate();
                acctStatus = user.getAcctStatus();
                gender = user.getGender();
                loginLanguage = user.getLoginLanguage();
            }
            ctx.put("userId", userId);
            ctx.put("username", username);
            ctx.put("firstName", firstName);
            ctx.put("role", role);
            ctx.put("orgId", orgId);
            ctx.put("orgName", orgName);
            ctx.put("postnId", postnId);
            ctx.put("postnName", postnName);
            ctx.put("corpId", corpId);
            ctx.put("corpName", corpName);
            ctx.put("userIcon", userIcon);
            //经销商Id
            ctx.put("acctId", acctId);
            //经销商姓名
            ctx.put("acctName", acctName);
            //用户类型
            ctx.put("userType", userType);
            //用户类型
            ctx.put("lastLoginDate", lastLoginDate);
            //客户状态
            ctx.put("acctStatus", acctStatus);
            ctx.put("gender", gender);
            // 使用语言
            ctx.put("loginLanguage", loginLanguage);

            CoreEnterprise enterprise = SecurityInterceptor.tempEnterpirse.get();
            String isMultiPriceList = "";
            Long vAcctId = null;
            String vAcctName = "";
            String industryVersion = null;
            if (enterprise != null) {
                isMultiPriceList = enterprise.getIsMultiPriceList();
                vAcctId = enterprise.getvAcctId();
                vAcctName = enterprise.getvAcctName();
                industryVersion = enterprise.getIndustryVersion();
            }

            //如果经销商id 不为空，则查询出当前用户的价格表返回前端
            //HuangLJ 2018年07月20日
            //价格表Id
            Long priceListId = null;
            //价格表名称
            String priceListName = "";
            if (acctId != null) {
                try {
                    Orgnization orgnizationQuery = new Orgnization();
                    orgnizationQuery.setAcctId(acctId);
                    orgnizationQuery.setPageFlag(false);
                    List<Orgnization> orgnizationList = orgnizationService.queryByExamplePage(orgnizationQuery);
                    if (orgnizationList != null && orgnizationList.size() > 0) {
                        priceListId = orgnizationList.get(0).getPriceListId();
                        priceListName = orgnizationList.get(0).getPriceListName();
                    }
                } catch (Exception e) {
                    LCLogger.withException(e);
                }
            }

            if (orgId == null) {
                throw new BasicServiceException("orgId不能为空");
            }

            ctx.put("isMultiPriceList", isMultiPriceList);
            ctx.put("priceListId", priceListId);
            ctx.put("priceListName", priceListName);
            ctx.put("_ctxPath", request.getContextPath());
            ctx.put("vAcctId", vAcctId);
            ctx.put("vAcctName", vAcctName);
            ctx.put("industryVersion", industryVersion);
            result.put("success", true);
            result.put("result", ctx);
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("result", e.getMessage());
        }
        return result;
    }

    /**
     * crm 登录入口
     *
     * @param username
     * @param password
     * @param request
     * @return RespDTO
     * @throws Exception
     */
    @RequestMapping(method = {RequestMethod.POST}, value = "/login")
    public RespDTO login(@RequestParam String username,
                         @RequestParam String password,
                         @RequestParam String language,
                         String token,
                         String platformType,
                         HttpServletRequest request) throws Exception {
        try {
            long starttime = System.currentTimeMillis();
            String newPassword = PasswordUtil.decryptString(password);
            RespDTO<LoginDTO> dto = userService.login(username, newPassword, "crmLogin", request, language);
            //是否需要跳转至修改密码界面 暂定-2为需要跳转的错误编码
            int needChangePwCode = -2;
            if (needChangePwCode == dto.getCode()) {
                return dto;
            }
            loginLogService.addLoginLogByRespDTO(dto, request);
            LoginDTO loginDTO = (LoginDTO) dto.getData();
            User user = loginDTO.getUser();
            if (StringUtils.isNotBlank(token) && StringUtils.isNotBlank(platformType)) {
                this.webBindThirdAccount(token, platformType, user.getId(), user.getCorpid(), "CRM");
            }
            long endtime = System.currentTimeMillis();
            logger.error("login:login:" + (FunctionTimeUtil.div((endtime - starttime), 1000, 3)));

            LoginDTO dtoData = dto.getData();
            dtoData.setExpires(dtoData.getExpires() * 1000);
            return dto;
        } catch (Exception e) {
            LCLogger.withException(e);
            RespDTO respDTO = new RespDTO();
            respDTO.setError(e.getMessage());
            respDTO.setCode(-1);
            return respDTO;
        }
    }

    /**
     * 移动端登录入口
     *
     * @param login
     * @param session
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/mobileLogin", method = {RequestMethod.POST})
    @ResponseBody
    public Map<String, Object> login(@JsonParam User login, HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        // 设备UUID
        String deviceUUID = login.getDeviceUuid();
        // 账套ID
        String corpBase = request.getHeader("corpBase");
        // 登录Token
        String client_loginToken = request.getHeader("loginToken");
        String loginType = null;

        // QQ登录返回的token
        String qqToken = login.getAttr1();
        // 微信登录返回的token
        String wxToken = login.getAttr2();
        // 登录app的类型
        String appType = login.getAttr3();
        // 微信避开二次授权前端缓存的unionId
        String wxSecUnionId = login.getAttr4();
        // 微信避开二次授权UN前端缓存的openId
        String wxSecOpenId = login.getAttr5();

        Map<String, Object> result = new HashMap<>();

        // 登录名
        String username = login.getUsername();
        // 密码
        String password = login.getPassword();

        // 暂时先兼容导购助手/dms旧的请求方式,后续改版完成后删除
        if (StringUtils.isBlank(username)) {
            username = request.getParameter("j_username");
            password = request.getParameter("j_password");
        }
        LinkRedisClient j = null;
        try {
            /** 校验当前设备传入的UUID和表中记录的是否一致，如果多个账套登录过,可能会产生多个设备信息,但UUID是一样的 */
            if (StringUtils.isNotBlank(deviceUUID)) {
                Boolean deviceLocked = validDeviceLocked(deviceUUID);
                if (deviceLocked) {
                    throw new BasicServiceException("设备已锁定，请联系管理员处理！");
                }
            }

            // 服务端生成loginToken，若client_loginToken在有效期内，则server_loginToken == client_loginToken
            String server_loginToken = "";
            j = RedisUtil.getJedis();
            /** 根据用户名从数据库查询 */
            User user = userService.queryByUserName(username);
            if (user == null) {
                throw new BasicServiceException("用户名或密码错误，请确认！");
            } else {
                //校验失败次数
                userService.checkLoginErrorTimes(username);
            }

            /** 用户有效性判断 */
            String status = user.getStatus();
            String valid = "有效";
            if (!valid.equals(status)) {
                throw new Exception("用户已失效，如有需要，请联系管理员！");
            }

            /** 密码校验，若password不为空，则优先采用password进行安全登录 */
            if (StringUtils.isNotBlank(password)) {
                if (!this.isPassValid(user.getPassword(), password, user)) {
                    throw new BasicServiceException("用户名或密码错误，请确认！");
                }
                /** 密码校验通过，生成loginToken */
                server_loginToken = userService.mobileGetLoginToken(username, user.getCorpid(), deviceUUID, password, APP_ENTRANCE);
                // 密码登录情况下，如果参数存在QQ/微信认证信息，则绑定QQ、微信
                if (StringUtils.isNotBlank(qqToken)) {
                    JSONObject qqAuthInfo = thirdLoginService.getQQAuthInfo(qqToken);
                    thirdLoginService.bindQQ(qqAuthInfo.getString("unionid"),
                            qqAuthInfo.getString("openid"),
                            appType,
                            "QQ",
                            user.getId(),
                            user.getCorpid());
                    result.put("unionId", qqAuthInfo.getString("unionid"));
                    result.put("openId", qqAuthInfo.getString("openid"));
                    result.put("accessToken", qqToken);
                }

                if (StringUtils.isNotBlank(wxToken)) {
                    Map<String, String> authInfo = thirdLoginService.getAuthInfoFromRedis(wxToken);
                    String unionId = authInfo.get("unionid");
                    String openId = authInfo.get("openId");
                    String accessToken = authInfo.get("access_token");
                    String refreshToken = authInfo.get("refresh_token");
                    thirdLoginService.bindWx(unionId, openId, appType, "WX", user.getId(), user.getCorpid());
                    //以unionId+openId为key，保存accessToken,refreshToken到redis
                    thirdLoginService.saveThirdInfo(unionId, openId, accessToken, refreshToken, "WX");
                    result.put("unionId", unionId);
                    result.put("openId", openId);
                    result.put("accessToken", accessToken);
                }
            } else if (StringUtils.isNotBlank(client_loginToken)) {
                // 校验loginToken合法性
                server_loginToken = userService.verifyLoginToken(username, user.getCorpid(), deviceUUID, client_loginToken);
                if (StringUtils.isBlank(server_loginToken)) {
                    throw new BasicServiceException("auto_login_fail");
                }
            } else if (StringUtils.isNotBlank(qqToken)) {
                // QQ/微信已绑定账号登录逻辑
                JSONObject qqAuthInfo = thirdLoginService.getQQAuthInfo(qqToken);
                if (!qqAuthInfo.getString("unionid").equals(user.getQqUnionId())) {
                    throw new BasicServiceException("该QQ未找到绑定账号");
                }
                server_loginToken = userService.mobileGetLoginToken(username, user.getCorpid(), deviceUUID, password, APP_ENTRANCE);
            } else if (StringUtils.isNotBlank(wxToken)) {
                // 微信已绑定账号登录逻辑
                Map<String, String> authInfo = thirdLoginService.getAuthInfoFromRedis(wxToken);
                String unionId = authInfo.get("unionid");
                String openId = authInfo.get("openId");
                String accessToken = authInfo.get("access_token");
                String refreshToken = authInfo.get("refresh_token");
                if (!unionId.equals(user.getWxUnionId())) {
                    throw new BasicServiceException("该微信号未找到绑定账号");
                }
                server_loginToken = userService.mobileGetLoginToken(username, user.getCorpid(), deviceUUID, password, APP_ENTRANCE);
                //以unionId+openId为key，保存accessToken,refreshToken到redis
                thirdLoginService.saveThirdInfo(unionId, openId, accessToken, refreshToken, "WX");
                result.put("unionId", unionId);
                result.put("openId", openId);
                result.put("accessToken", accessToken);
            } else if (StringUtils.isNotBlank(wxSecUnionId) && StringUtils.isNotBlank(wxSecOpenId)) {
                //微信避开二次授权登录
                if (!wxSecUnionId.equals(user.getWxUnionId())) {
                    throw new BasicServiceException("该微信号未找到绑定账号");
                }
                server_loginToken = userService.mobileGetLoginToken(username, user.getCorpid(), deviceUUID, password, APP_ENTRANCE);
                String redisKey = wxSecUnionId + "_" + wxSecOpenId;
                String accessToken;
                boolean existed = j.exists(redisKey);
                if (existed) {
                    accessToken = j.hget(redisKey, "accessToken");
                } else {
                    throw new BasicServiceException("未找到缓存信息");
                }
                result.put("unionId", wxSecUnionId);
                result.put("openId", wxSecOpenId);
                result.put("accessToken", accessToken);
            } else {
                throw new Exception("用户名或密码错误，请确认！");
            }

            /** 控制只允许110帐套的用户登录营销助手 */
            if (StringUtils.isNotBlank(corpBase)) {
                if (!user.getCorpid().equals(PasswordUtil.getBase64Decoder(corpBase))) {
                    throw new BasicServiceException("当前账号无法登陆营销助手,请联系管理员进行处理！");
                }
            }

            // 根据当前用户设置登录类型
            String dealerEmployee = "DealerEmployee";
            String terminalEmployee = "TerminalEmployee";
            String vendorEmployee = "VendorEmployee";

            if (dealerEmployee.equals(user.getEmpType())) {
                loginType = DMS_APP;
            } else if (terminalEmployee.equals(user.getEmpType())) {
                loginType = GUIDE_APP;
            } else if (vendorEmployee.equals(user.getEmpType())) {
                loginType = CRM_APP;
            }

            /*设置当前登录设备类型*/
            user.setLoginType(loginType);

            /** 生成token，并将user放到session中*/

            String redisKey = username + "_" + user.getCorpid() + "_" + deviceUUID;
            String token = "";
            int tokenExpire = 0;
            JWT jwt = null;
            if (StringUtils.isBlank(deviceUUID)) {
                jwt = userService.getAccessToken(username, password, StringUtils.isBlank(appType) ? null : "mp",
                        null, null, APP_ENTRANCE);
                if (jwt == null) {
                    throw new BasicServiceException("获取认证信息异常!");
                }
                token = jwt.getAccess_token();
                tokenExpire = jwt.getExpires_in();
            } else {
                token = j.hget(redisKey, "access_token");
                tokenExpire = StringUtils.isNotBlank(j.hget(redisKey, "expires_in")) ? Integer.parseInt(j.hget(redisKey, "expires_in")) : 0;
            }
            session.setAttribute("token", token);
            session.setAttribute(token, user);
            // 获取ip地址
            String ip = IpUtil.getIpAddress(request);
            user.setIpAddress(ip);
            LoginLog record = new LoginLog();
            record.setLockFlag('N');
            record.setUserId(user.getId());
            record.setLoginName(user.getUsername());
            record.setIpAddress(ip);
            record.setUserSource(loginType);
            record.setAccessToken(token);
            record.setLoginType(loginType);
            loginLogService.addLoginSuccessLog(record);
            //认证成功后将登录用户信息存到redis

            SecurityInterceptor.token.set(token);
            //把用户放到线程里面。保证下面的操作。是基于当前登录用户。
            if (StringUtils.isNull(user.getCurClientId())) {
                user.setCurClientId(APP_ENTRANCE);
            }
            SecurityInterceptor.tempUser.set(user);

            userService.setLoginInfo(token, user, "", tokenExpire, APP_ENTRANCE, null);

            /** HuangLJ 2017年12月19日 添加在线用户信息，如果添加报错，不能影响登录 */
            try {
                addOnlineEmp(user, session, request);
            } catch (Exception e) {
                LCLogger.withException(e);
                LCLogger.error().withMessageKey("mobileLogin")
                        .withMessage(e.getMessage()).flush();
            }

            /** user对象存入Redis，用于自带token的请求在拦截器中获取user对象 */
            String userJsonStr = JSON.toJSONString(user);
            j.set(token, userJsonStr);
            j.expire(token, tokenExpire);

            /** 报表平台专用：登录成功后给user对象绑定一个reportToken参数 */
            userService.bindingUserAndToken(user, token, tokenExpire);

            /** 清空用户对象中的密码字符串 */
            user.setPassword("");


            result.put("result", user);
            // 小程序专用
            result.put("token", token);
            // 自动登录Token
            result.put("loginToken", server_loginToken);
            result.put("success", true);
        } catch (Exception e) {
            LCLogger.withException(e);
            LCLogger.error().withMessageKey("mobileLogin")
                    .withMessage("登录失败" + e.getMessage()).flush();
            result.put("success", false);
            result.put("message", e.getMessage());
        } finally {
            RedisUtil.returnResource(j);
        }
        return result;
    }


    @RequestMapping(method = {RequestMethod.POST}, value = "/publicKey")
    public Map<String, Object> login(HttpServletRequest request) throws Exception {
        Map<String, Object> result = new HashMap<String, Object>();
        try {
            String publicKey = PasswordUtil.loadPublicKeyStream();
            result.put("success", true);
            result.put("publicKey", publicKey);
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("result", "获取加密公钥失败！");
        }
        return result;
    }

    /**
     * dingding 登录入口
     *
     * @param request
     * @return RespDTO
     * @throws Exception
     */
    @RequestMapping(method = {RequestMethod.POST}, value = "/dingdingLogin")
    public RespDTO dingdingLogin(@RequestParam String authCode,
                                 HttpServletRequest request) throws Exception {
        try {
            long starttime = System.currentTimeMillis();
            RespDTO<LoginDTO> dto = userService.dingdingLogin(authCode, "crmLogin", request);
            //是否需要跳转至修改密码界面 暂定-2为需要跳转的错误编码
            int needChangePwCode = -2;
            if (needChangePwCode == dto.getCode()) {
                return dto;
            }
            loginLogService.addLoginLogByRespDTO(dto, request);
            return dto;
        } catch (Exception e) {
            LCLogger.withException(e);
            RespDTO respDTO = new RespDTO();
            respDTO.setError(e.getMessage());
            respDTO.setCode(-1);
            return respDTO;
        }
    }

    /**
     * api 登录入口
     *
     * @param clientId 客户端Id
     * @param password 客户端秘钥
     */
    @RequestMapping(method = {RequestMethod.POST}, value = "/apilogin")
    public Map<String, Object> apilogin(@RequestParam(name = "clientId", required = false) String clientId,
                                        @RequestParam(name = "password", required = false) String password,
                                        @RequestParam(name = "username", required = false) String username,
                                        HttpServletRequest request) {
        Map<String, Object> result = new HashMap<>();

        try {
            if (StringUtils.isBlank(clientId) || StringUtils.isBlank(password)) {
                throw new BasicServiceException("客户端id和密码都不能为空");
            }

            RespDTO dto = userService.apiLogin(clientId, password, username, request);
            loginLogService.addLoginLogByRespDTO(dto, request);
            LoginDTO loginDTO = (LoginDTO) dto.getData();
            result.put("success", true);
            result.put("result", loginDTO.getToken());
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("result", e.getMessage());
        }
        return result;
    }

    @RequestMapping(method = {RequestMethod.POST}, value = "/login2")
    public RespDTO login2(@RequestParam String username, @RequestParam String password, HttpServletRequest request) throws Exception {
        try {
            String newPassword = PasswordUtil.decryptString(password);
            RespDTO dto = userService.login(username, newPassword, "crmLogin", request, "");

            LoginDTO loginDTO = (LoginDTO) dto.getData();
            User user = loginDTO.getUser();
            //IpUtil获取IP地址
            String ip = IpUtil.getIpAddress(request);
            LoginLog record = new LoginLog();
            record.setLockFlag('N');
            String userAgent = request.getHeader("User-Agent");
            record.setUserId(user.getId());
            record.setLoginName(user.getUsername());
            record.setIpAddress(ip);
            record.setUserAgent(userAgent);
            //crm用户登录
            record.setUserSource("CRM");
            record.setAccessToken(loginDTO.getToken());
            record.setLoginType("CRM");
            loginLogService.addLoginSuccessLog(record);
            loginDTO.setExpires(loginDTO.getExpires() * 1000);
            return dto;
        } catch (Exception e) {
            LCLogger.withException(e);
            RespDTO respDTO = new RespDTO();
            respDTO.setError(e.getMessage());
            respDTO.setCode(-1);
            return respDTO;
        }
    }

    /**
     * dms 登录入口
     *
     * @param username
     * @param password
     * @param request
     * @return RespDTO
     * @throws Exception
     */
    @RequestMapping(method = {RequestMethod.POST}, value = "/dmslogin")
    public RespDTO dmslogin(@RequestParam String username,
                            @RequestParam String password,
                            String token,
                            String platformType,
                            String appType,
                            HttpServletRequest request) throws Exception {
        try {
            String newPassword = PasswordUtil.decryptString(password);
            RespDTO dto = userService.login(username, newPassword, "dmsLogin", request, "");

            LoginDTO loginDTO = (LoginDTO) dto.getData();
            User user = loginDTO.getUser();
            //IpUtil获取IP地址
            String ip = IpUtil.getIpAddress(request);
            LoginLog record = new LoginLog();
            record.setLockFlag('N');
            String userAgent = request.getHeader("User-Agent");
            record.setUserId(user.getId());
            record.setLoginName(user.getUsername());
            record.setIpAddress(ip);
            record.setUserAgent(userAgent);
            //crm用户登录
            record.setUserSource("DMS");
            record.setAccessToken(loginDTO.getToken());
            record.setLoginType("DMS");
            loginLogService.addLoginSuccessLog(record);
            if (StringUtils.isNotBlank(token) && StringUtils.isNotBlank(platformType)) {
                this.webBindThirdAccount(token, platformType, user.getId(), user.getCorpid(), appType);
            }
            loginDTO.setExpires(loginDTO.getExpires() * 1000);
            return dto;
        } catch (Exception e) {
            LCLogger.withException(e);
            RespDTO respDTO = new RespDTO();
            respDTO.setError(e.getMessage());
            respDTO.setCode(-1);
            return respDTO;
        }
    }

    /**
     * 小程序登录入口
     *
     * @return 当前登录者的信息
     * @author LiQun
     */
    @RequestMapping(value = "/mpLogin", produces = "application/json")
    @ResponseBody
    public Map<String, Object> mpLogin(@RequestBody User user, HttpSession session, HttpServletRequest request,
                                       HttpServletResponse response) {
        Map<String, Object> result = new HashMap<String, Object>();

        try {
            //设置用户登录ip
            user.setIpAddress(IpUtil.getIpAddress(request));
            RespDTO respDTO = userService.mpLogin(user);
            LoginDTO loginDTO = (LoginDTO) respDTO.getData();
            // 返回结果
            result.put("session_key", loginDTO.getSessionKey());
            result.put("result", loginDTO.getAccount());
            result.put("token", loginDTO.getToken());
            result.put("success", true);
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("message", e.getMessage());
        }
        return result;
    }


    /**
     * 企业微信小程序登录入口
     *
     * @return 当前登录者的信息
     * @author GuoShan
     */
    @RequestMapping(value = "/corpWxMpLogin")
    @ResponseBody
    public Map<String, Object> corpWxMpLogin(User user, HttpSession session, HttpServletRequest request,
                                             HttpServletResponse response) {
        Map<String, Object> result = new HashMap<String, Object>();

        try {
            //设置用户登录ip
            String ipAddress = IpUtil.getIpAddress(request);
            user.setIpAddress(ipAddress);
            RespDTO respDTO = userService.corpWxMpLogin(user);
            LoginDTO loginDTO = (LoginDTO) respDTO.getData();

            User dtoUser = loginDTO.getUser();

            LoginLog record = new LoginLog();
            record.setLockFlag('N');
            String username = dtoUser.getUsername();
            record.setLoginName(username);
            record.setIpAddress(ipAddress);
            record.setUserSource("CORP_WX_MP");
            record.setAccessToken(loginDTO.getToken());
            record.setLoginType("CORP_WX_MP");
            record.setUserId(dtoUser.getId());
            loginLogService.addLoginSuccessLog(record);
//            result.put("session_key", loginDTO.getSessionKey());
            // 返回结果


            List<AppMenuVO> appMenuVOList = loginService.getUserAppMenuList(dtoUser);
            result.put("menus", appMenuVOList);
            result.put("result", dtoUser);
            result.put("token", loginDTO.getToken());
            result.put("expires", loginDTO.getExpires());
            result.put("success", true);
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("message", e.getMessage());
        }
        return result;
    }


    /**
     * HuangLj 2018年07月23日
     *
     * @param request 请求
     * @return Map
     * @throws Exception 报错
     *                   解锁用户
     */
    @RequestMapping(method = {RequestMethod.POST}, value = "/unlockUser")
    public Map<String, Object> unlockUser(@RequestParam String username, HttpServletRequest request) throws Exception {

        Map<String, Object> result = new HashMap<String, Object>();
        LinkRedisClient jedis = null;
        try {
//          CoreUser user = UserUtil.getUser();
//          String userName = user.getUsername();
            String userName = username.toUpperCase();
            jedis = RedisUtil.getJedis();
            String key = "crm_loginError_info";
            jedis.hdel(key, userName);
            result.put("success", true);
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("result", e.getMessage());
        } finally {
            RedisUtil.returnResource(jedis);
        }
        return result;
    }


    /**
     * 添加到在线用户列表
     *
     * @param user    登录用户
     * @param session
     * @param request
     */
    private void addOnlineEmp(User user, HttpSession session, HttpServletRequest request) {
        OnlineUser onlineUser = new OnlineUser();
        // 设置日期格式
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String date = df.format(new Date());
        onlineUser.setIpAddress(IpUtil.getIpAddress(request));
        // web端登录标识
        onlineUser.setLoginType("APP");
        // 会话ID
        onlineUser.setSessionId(session.getId());
        onlineUser.setUsername(user.getUsername());
        onlineUser.setEmpType(user.getEmpType());
        onlineUser.setLoginTime(date);
        onlineUser.setFirstName(user.getFirstName());
        String jsonOnlineUser = JSONObject.toJSONString(onlineUser);
        session.setAttribute("online", jsonOnlineUser);
    }

    public boolean isPassValid(String encPass, String rawPass, User user) {
        if (PasswordUtil.isEquals(rawPass, encPass)) {
            return true;
        } else {
            setRedisInfo(user.getUsername().toUpperCase());
            return false;
        }
    }

    /**
     * 验证失败之后，在Redis中设置失败次数
     *
     * @param username
     */
    private void setRedisInfo(String username) {
        LinkRedisClient j = null;
        try {
            j = RedisUtil.getJedis();
            String redisKey = "app_loginError_info";
            String currentdate = DateUtil.dateToStr(new Date(), "yyyy-MM-dd HH:mm:ss");
            System.out.println(username + "密码错误！");
            if (j.exists(redisKey) && j.hmget(redisKey, username).size() > 0) {
                Map<String, String> map = new HashMap<>();
                map.put(username,
                        (Integer.parseInt(j.hmget(redisKey, username).get(0).split("\\++")[0]) + 1) + "+" + currentdate);
                j.hdel(redisKey, username);
                j.hmset(redisKey, map);
            }
        } finally {
            RedisUtil.returnResource(j);
        }
    }


    /**
     * 校验设备是否被锁定
     *
     * @param deviceUUID 设备的uuid
     * @return 设备被锁定时, 返回true, 否则返回false
     * @throws Exception
     */
    private Boolean validDeviceLocked(String deviceUUID) throws Exception {
        AppMobileInfo mobileInfo = new AppMobileInfo();
        mobileInfo.setUuid(deviceUUID);
        List<AppMobileInfo> mobileInfoList = appMobileInfoService.getMobileInfo(mobileInfo);
        String deviceLock;
        /** 校验当前设备是否已经被锁定 */
        if (mobileInfoList != null) {
            for (AppMobileInfo info : mobileInfoList) {
                deviceLock = info.getDeviceLock();
                /** 设备已经被锁定 */
                if ("Y".equals(deviceLock)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**************** 微信&QQ账号关联-start*************/
    /**
     * 微信&QQ账号关联-绑定用户
     *
     * @author ouyangzhenqiang
     */
    @RequestMapping(value = "/bindThirdClientUser", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> bindThirdClientUser(@RequestBody User user, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> result = new HashMap<String, Object>();
        String login = UserUtil.getUser().getUsername();
        Long userId = UserUtil.getUser().getId();
        String wxUnionId = user.getWxUnionId();
        String qqUnionId = user.getQqUnionId();
        try {
            if (StringUtils.isNotBlank(wxUnionId)) {
                /** 微信绑定校验 */
                User tempUser = new User();
                tempUser.setUsername(login);
                tempUser = userService.getBoundAccounts(tempUser);
                if (StringUtils.isNotBlank(tempUser.getWxUnionId())) {
                    throw new Exception("您登录的账号已经绑定了其他微信账号，不能重复绑定！");
                }
                tempUser = new User();
                tempUser.setWxUnionId(wxUnionId);
                tempUser = userService.getBoundAccounts(tempUser);
                if (tempUser != null) {
                    throw new Exception("您的授权微信账号已经绑定了其他系统账号，不能重复绑定！");
                }
                tempUser = new User();
                tempUser.setWxUnionId(wxUnionId);
                tempUser.setId(userId);
                userService.thirdClientBindUser(tempUser);
            } else if (StringUtils.isNotBlank(qqUnionId)) {
                /** QQ绑定校验 */
                User tempUser = new User();
                tempUser.setUsername(login);
                tempUser = userService.getBoundAccounts(tempUser);
                if (StringUtils.isNotBlank(tempUser.getQqUnionId())) {
                    throw new Exception("您登录的账号已经绑定了其他QQ账号，不能重复绑定！");
                }
                tempUser = new User();
                tempUser.setQqUnionId(qqUnionId);
                tempUser = userService.getBoundAccounts(tempUser);
                if (tempUser != null) {
                    throw new Exception("您的授权QQ账号已经绑定了其他系统账号，不能重复绑定！");
                }
                tempUser = new User();
                tempUser.setQqUnionId(qqUnionId);
                tempUser.setId(userId);
                userService.thirdClientBindUser(tempUser);
            } else {
                throw new Exception("第三方授权Id信息为空，请确认是否授权成功！");
            }
            result.put("success", true);
            result.put("message", "绑定成功！");
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("message", e.getMessage());
        }
        return result;
    }

    /**
     * 微信&QQ账号关联-解除绑定
     *
     * @author ouyangzhenqiang
     */
    @RequestMapping(value = "/unBoundAccount", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> unBoundAccount(@RequestBody User user, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> result = new HashMap<String, Object>();
        Long userId = UserUtil.getUser().getId();
        String wxUnionId = user.getWxUnionId();
        String qqUnionId = user.getQqUnionId();
        try {
            User tempUser = new User();
            tempUser.setId(userId);
            if (StringUtils.isNotBlank(wxUnionId)) {
                tempUser.setWxUnionId(wxUnionId);
                tempUser.setClient("weChat");
            } else if (StringUtils.isNotBlank(qqUnionId)) {
                tempUser.setQqUnionId(qqUnionId);
                tempUser.setClient("QQ");
            } else {
                throw new Exception("第三方授权Id信息为空，解绑失败！");
            }
            userService.unBoundAccount(tempUser);
            result.put("success", true);
            result.put("message", "已解绑！");
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("message", e.getMessage());
        }
        return result;
    }

    /**************** 微信&QQ账号关联-end*************/

    @RequestMapping(value = "/loginfail", method = RequestMethod.POST)
    public ModelAndView loginfail(HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        ModelAndView mav = new ModelAndView();
        mav.setViewName("index");
        return mav;
    }

    /**
     * QQ\微信登录之后，登录本系统账号自动绑定QQ\微信
     *
     * @author cuizhiyong
     * @param token    前后端交互key
     * @param platform 平台类型QQ(QQ平台),WX(微信平台)
     * @deprecated date 2019/4/3
     */
    private void webBindThirdAccount(String token, String platform, Long userId, Long corpId, String appType) throws Exception {
        LinkRedisClient jedis = null;
        try {
            jedis = RedisUtil.getJedis();
            boolean existed = jedis.exists(token);
            if (!existed) {
                throw new BasicServiceException("token已过期,请重新授权");
            }
            if (StringUtils.isBlank(appType)) {
                throw new BasicServiceException("请传入appType");
            }
            String unionId = jedis.hget(token, "unionid");
            String openId = jedis.hget(token, "openId");
            jedis.del(token);
            if ("QQ".equals(platform)) {
                thirdLoginService.bindQQ(unionId, openId, appType, "QQ", userId, corpId);
            } else if ("WX".equals(platform)) {
                thirdLoginService.bindWx(unionId, openId, appType, "WX", userId, corpId);
            } else {
                throw new BasicServiceException("平台类型错误");
            }
        } finally {
            RedisUtil.returnResource(jedis);
        }
    }

    @RequestMapping(value = "/oauthToken", method = {RequestMethod.POST})
    @ResponseBody
    public Map<String, Object> oauthToken(@RequestParam String username,
                                          @RequestParam String token,
                                          HttpSession session,
                                          HttpServletRequest request,
                                          HttpServletResponse response) throws Exception {
        Map<String, Object> result = new HashMap<>();
        result.put("code", "01");
        result.put("message", "未知错误");
        if (!"YibinOA_landray".equals(token)) {
            result.put("code", "02");
            result.put("message", "token错误");
        } else if (StringUtils.isBlank(username)) {
            result.put("code", "03");
            result.put("message", "参数缺失");
        } else {
            User user = userService.queryByUserName(username);
            if (null == user) {
                result.put("code", "04");
                result.put("message", "用户不存在");
            } else {
                String oatoken = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
                OauthToken oauthToken = new OauthToken();
                oauthToken.setOauthToken(oatoken);
                oauthToken.setTokenOverTime(300000);
                oauthToken.setUserId(user.getId());
                oauthToken.setUserName(user.getUsername());
                try {
                    oauthTokenService.addOauthToken(oauthToken);
                    result.put("code", "00");
                    result.put("message", "调用成功");
                    result.put("token", oatoken);
                } catch (Exception e) {
                    result.put("code", "09");
                    result.put("message", "异常");
                }
            }
        }
        return result;
    }

    /**
     * crm 认证token登录
     */
    @RequestMapping(method = {RequestMethod.POST}, value = "/oauthTokenLogin")
    public RespDTO oauthTokenLogin(@RequestParam String username,
                         @RequestParam String oauthToken,
                         String token,
                         String platformType,
                         HttpServletRequest request) throws Exception {
        Map<String, String> respData = new HashMap<>();
        username = username.toUpperCase();
        respData.put("username", username);
        try {
            // 认证token校验，通过后免密登录
            OauthToken otoken = oauthTokenService.queryByToken(oauthToken);
            if (null == otoken || !otoken.getUserName().equals(username)) {
                throw new Exception("登录认证错误！");
            } else if (otoken.getLastUpdatedBy() != 1 || System.currentTimeMillis() - otoken.getCreateTime().getTime() > otoken.getTokenOverTime()) {
                throw new Exception("登录认证失效！");
            }
            RespDTO<LoginDTO> dto = userService.login(username, null, "oauthTokenLogin", request, null);

            loginLogService.addLoginLogByRespDTO(dto, request);
            LoginDTO loginDTO = (LoginDTO) dto.getData();
            User user = loginDTO.getUser();
            if (StringUtils.isNotBlank(token) && StringUtils.isNotBlank(platformType)) {
                this.webBindThirdAccount(token, platformType, user.getId(), user.getCorpid(), "CRM");
            }

            LoginDTO dtoData = dto.getData();
            dtoData.setExpires(dtoData.getExpires() * 1000);
            return dto;
        } catch (Exception e) {
            LCLogger.withException(e);
            RespDTO respDTO = new RespDTO();
            respDTO.setError(e.getMessage());
            respDTO.setCode(-1);
            respDTO.setData(respData);
            return respDTO;
        }
    }

}